﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BesAsm.Stormwater.HspfCore;

namespace BesAsm.Stormwater.HspfResults
{ 
  public abstract class L61Block
  {
    private L61Fluxes _fluxes;
    private L61StateVariables _stateVariables;
    private L61ResultsTimePeriod _timePeriod;
    private ILandSegment _segment;
    private DateTime _resultsDate;    

    public abstract int BlockLineCount { get; }

    public L61Block(ILandSegment segment)
    {
      _segment = segment;
      _fluxes = new L61Fluxes(segment.Type);
      _stateVariables = new L61StateVariables(segment.Type);
    }        

    public L61Fluxes Fluxes
    {
      get { return _fluxes; }
      set { _fluxes = value; }
    }

    public L61StateVariables States
    {
      get { return _stateVariables; }
      protected set { _stateVariables = value; } 
    }

    public ILandSegment Segment
    {
      get { return _segment; }      
    }

    public DateTime ResultsDate
    {
      get { return _resultsDate; }
      protected set { _resultsDate = value; }
    }

    public void AddBlockLines(List<string> blockLines)
    {
      if (blockLines.Count != BlockLineCount)
        throw new ArgumentException("Incorrect line count");

      this.States = ParseStates(blockLines);
      this.Fluxes = ParseFluxes(blockLines);

      this.ResultsDate = ParseDate(blockLines);
      this.ResultsTimePeriod = ParseBlockType(blockLines);
    }

    public L61ResultsTimePeriod ResultsTimePeriod
    {
      get { return _timePeriod; }
      protected set { _timePeriod = value; }
    }

    protected abstract L61StateVariables ParseStates(List<string> blockLines);
    protected abstract L61Fluxes ParseFluxes(List<string> blockLines);

    protected L61ResultsTimePeriod ParseBlockType(List<string> blockLines)
    {
      string headerLine = blockLines.Find(p => p.Contains("REPORT FOR "));

      if (headerLine.Contains("REPORT FOR PRINTOUT YEAR"))
        return L61ResultsTimePeriod.Yearly;
      else if (headerLine.Contains("REPORT FOR MONTH"))
        return L61ResultsTimePeriod.Monthly;
      else
        throw new ArgumentException("Unable to determine block time period");
    }

    protected DateTime ParseDate(List<string> blockLines)
    {
      string headerLine = blockLines.Find(p => p.Contains("REPORT FOR "));

      string[] headerTokens = headerLine.Split(
        new char[] { ' ', '/' },
        StringSplitOptions.RemoveEmptyEntries);

      int month = int.Parse(
        headerTokens[headerTokens.Length - 1]);
      int year = int.Parse(
        headerTokens[headerTokens.Length - 2]);
      int day = DateTime.DaysInMonth(year, month);

      DateTime dt = new DateTime(year, month, day);

      return dt;
    }

    public abstract Dictionary<string, object> GetResultsDictionary();
        
  }

  public enum L61ResultsTimePeriod
  {
    Monthly, Yearly
  }

}
